#include <Windows.h>
#include <CommCtrl.h>
#include <stdlib.h>
#include "Core/Log/LogManager.h"
//#include "../Layout/VerticalLayout.h"
//#include "../Layout/HorizontalLayout.h"
//#include "../Button/Button.h"
//#include "../Slider/Slider.h"
//#include "../Tab/Tab.h"
#include "Window.h"
#include "Application.h"

namespace GUI
{
	namespace Win32
	{
		int Application::ms_idGenerator = 0;
		std::map<int, Core::GUI::IWidget*> Application::ms_WidgetList;

		void Application::RegisterWidget(Core::GUI::IWidget * _pWidget)
		{
			if (ms_WidgetList.find(_pWidget->GetId()) == ms_WidgetList.end())
			{
				LOG_INFO("Registering %p[%d]", _pWidget, _pWidget->GetId());
				ms_WidgetList[_pWidget->GetId()] = _pWidget;
			}
			else
			{
				LOG_ERROR("[%d] already registered", _pWidget->GetId());
			}
		}

		void Application::UnregisterWidget(Core::GUI::IWidget * _pWidget)
		{
			auto it = ms_WidgetList.find(_pWidget->GetId());
			if (it != ms_WidgetList.end())
			{
				LOG_INFO("Unregistered [%p]%d", _pWidget, _pWidget->GetId());
				ms_WidgetList.erase(it);
			}
			else
			{
				LOG_ERROR("Cannot unregister [%d]", _pWidget->GetId());
			}
		}

		Application::Application()
		{

		}

		Application::~Application()
		{

		}

		Core::GUI::IWindow * Application::CreateWindowApp(const std::string & _strName, uint32 _iWidth, uint32 _iHeight)
		{
			Window * pWindow = new Window();
			if (!pWindow->Create(_strName, _iWidth, _iHeight))
			{
				delete pWindow;
				return NULL;
			}
			m_WindowList.push_back(pWindow);
			return pWindow;
		}

		void Application::DestroyWindowApp(Core::GUI::IWindow * _pWindow)
		{
			if (_pWindow)
			{
				auto it = std::find(std::begin(m_WindowList), std::end(m_WindowList), _pWindow);
				if (it != std::end(m_WindowList))
				{
					m_WindowList.erase(it);
				}
				else
				{
					LOG_ERROR("Unknown window %s", _pWindow->GetTitle());
				}
				delete (Window*)_pWindow;
			}
		}

		/*Core::GUI::IVerticalLayout * Application::CreateVerticalLayout(int _iWidth, int _iHeight, Core::GUI::eHorizontalJustify _hJusitfy, Core::GUI::eVerticalJustify _vJusitfy)
		{
			return new VerticalLayout(_iWidth, _iHeight, _hJusitfy, _vJusitfy, 0, 0, 0, 0);
		}

		Core::GUI::IVerticalLayout * Application::CreateVerticalLayout(int _iWidth, int _iHeight, Core::GUI::eHorizontalJustify _hJusitfy, Core::GUI::eVerticalJustify _vJusitfy, int _iMarginX, int _iMarginY, int _iPaddingX, int _iPaddingY)
		{
			return new VerticalLayout(_iWidth, _iHeight, _hJusitfy, _vJusitfy, _iMarginX, _iMarginY, _iPaddingX, _iPaddingY);
		}

		void Application::DestroyVerticalLayout(Core::GUI::IVerticalLayout * _pVerticalLayout)
		{
			if (_pVerticalLayout)
			{
				delete (VerticalLayout*)_pVerticalLayout;
			}
		}

		Core::GUI::IHorizontalLayout * Application::CreateHorizontalLayout(int _iWidth, int _iHeight, Core::GUI::eHorizontalJustify _hJusitfy, Core::GUI::eVerticalJustify _vJusitfy)
		{
			return new HorizontalLayout(_iWidth, _iHeight, _hJusitfy, _vJusitfy, 0, 0, 0, 0);
		}

		Core::GUI::IHorizontalLayout * Application::CreateHorizontalLayout(int _iWidth, int _iHeight, Core::GUI::eHorizontalJustify _hJusitfy, Core::GUI::eVerticalJustify _vJusitfy, int _iMarginX, int _iMarginY, int _iPaddingX, int _iPaddingY)
		{
			return new HorizontalLayout(_iWidth, _iHeight, _hJusitfy, _vJusitfy, _iMarginX, _iMarginY, _iPaddingX, _iPaddingY);
		}

		void Application::DestroyHorizontalLayout(Core::GUI::IHorizontalLayout * _pHorizontalLayout)
		{
			if (_pHorizontalLayout)
			{
				delete (HorizontalLayout*)_pHorizontalLayout;
			}
		}

		Core::GUI::IButton * Application::CreateButton(const std::string & _strName)
		{
			return new Button(_strName);
		}

		Core::GUI::IButton * Application::CreateButton(const std::string & _strName, int _iWidth, int _iHeight)
		{
			return new Button(_strName, _iWidth, _iHeight);
		}

		void Application::DestroyButton(Core::GUI::IButton * _pButton)
		{
			if (_pButton)
			{
				delete (Button*)_pButton;
			}
		}

		Core::GUI::ISlider * Application::CreateSlider(int _iMin, int _iMax, int _iDefaultValue)
		{
			return new Slider(_iMin, _iMax, _iDefaultValue);
		}

		Core::GUI::ISlider * Application::CreateSlider(int _iMin, int _iMax, int _iDefaultValue, int _iWidth, int _iHeight)
		{
			return new Slider(_iMin, _iMax, _iDefaultValue, _iWidth, _iHeight);
		}

		void Application::DestroySlider(Core::GUI::ISlider * _pSlider)
		{
			if (_pSlider)
			{
				delete (Slider*)_pSlider;
			}
		}

		Core::GUI::ITab * Application::CreateTab()
		{
			return new Tab();
		}

		Core::GUI::ITab * Application::CreateTab(int _iWidth, int _iHeight)
		{
			return new Tab(_iWidth, _iHeight);
		}

		void Application::DestroyTab(Core::GUI::ITab * _pTab)
		{
			if (_pTab)
			{
				delete (Tab*)_pTab;
			}
		}*/

		LRESULT CALLBACK Application::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
		{
			NMHDR *nmptr;
			int ctrlID;
			int requestID;
			int value; 
			HDC hdc;
			std::map<int, Core::GUI::IWidget*>::iterator it;
			switch (msg)
			{
			case WM_DESTROY:
				PostQuitMessage(0);
				break;

			case WM_ERASEBKGND:
				hdc = (HDC)wParam;
				

			case WM_PAINT:

				//std::cout << "Paint " << hWnd << std::endl;

				break;

			case WM_MOUSEMOVE:
				break;

			case WM_SIZE:
				break;

			case WM_NOTIFY:
				/*nmptr = (LPNMHDR)lParam;
				if (nmptr->code == TCN_SELCHANGE)
				{
					it = ms_WidgetList.find(nmptr->idFrom);
					if (it != ms_WidgetList.end())
					{
						auto pWidget = it->second;
						if (pWidget)
						{
							if (pWidget->GetType() == Core::GUI::Tab)
							{
								((Core::GUI::ITab*)pWidget)->ShowTab(TabCtrl_GetCurSel((HWND)nmptr->hwndFrom));
							}
						}
						else
						{
							LOG_ERROR("Widget NULL with id %d", wParam);
						}
					}
					else
					{
						LOG_ERROR("Widget not found with id %d", wParam);
					}
				}*/
				break;

			case WM_COMMAND:
				/*it = ms_WidgetList.find((int)wParam);
				if (it != ms_WidgetList.end())
				{
					auto pWidget = it->second;
					if (pWidget)
					{
						if (pWidget->GetType() == Core::GUI::Button)
						{
							((Core::GUI::IButton*)pWidget)->Click();
						}
					}
					else
					{
						LOG_ERROR("Widget NULL with id %d", wParam);
					}
				}
				else
				{
					LOG_ERROR("Widget not found with id %d", wParam);
				}*/
				break;

			case WM_HSCROLL:
				/*ctrlID = GetDlgCtrlID((HWND)lParam);
				value = HIWORD(wParam);
				requestID = LOWORD(wParam);
				it = ms_WidgetList.find(ctrlID);
				if (it != ms_WidgetList.end())
				{
					auto pWidget = it->second;
					if (pWidget)
					{
						if (pWidget->GetType() == Core::GUI::Slider)
						{
							switch (requestID)
							{
							case SB_LINELEFT:
								((Core::GUI::ISlider*)pWidget)->DecValue();
								break;
							case SB_LINERIGHT:
								((Core::GUI::ISlider*)pWidget)->IncValue();
								break;
							case SB_THUMBTRACK:
								((Core::GUI::ISlider*)pWidget)->SetValue(value);
								break;
							default:
								break;
							}
							
						}
					}
					else
					{
						LOG_ERROR("Widget NULL with id %d", wParam);
					}
				}
				else
				{
					LOG_ERROR("Widget not found with id %d", wParam);
				}*/
				break;

			default:
				return DefWindowProc(hWnd, msg, wParam, lParam);
			}

			return 0;
		}
	}
}